#include "tracker.h"
#include <sys/prctl.h>
#include <sys/thread_properties.h>
#include "sstream"
#include "ctime"

/// 游离的静态对象，需要对该对象的生命周期负责。
static pthread_t mainThread = 0;

void Tracker::trackerActionWithSignum(int signum, siginfo_t *info, void *invokeContext)
{
    if (signum == SIGUSR1)
    {
        /// then read thread frame, -----> armeabi-v7a
        auto *ucontext = reinterpret_cast<ucontext_t *>(invokeContext);
        mcontext_t mcontext = ucontext->uc_mcontext;

        uint64_t fp = mcontext.arm_fp;
        uint64_t lr = mcontext.arm_lr;
        std::stringstream ss;
        ss << "---------------------------------------------------" << std::endl
           << "Architecture: ";

#if defined(__arm__) || defined(_M_ARM)
        ss << "ARM";
#elif defined(__aarch64__)
        ss << "ARM64";
#endif
        ss << " " << TRACKER_TAG << std::endl
           << "record time: " << std::time(nullptr) << std::endl
           << "isolate_instructions: " << std::hex << baseIsolateInstructions << ", "
           << "vm_instructions: " << std::hex << baseVmInstructions << std::endl;
        int backline = 0;
        int deep = STACK_DEEP;
        while (fp && lr && deep--)
        {
            if (*((uint64_t *)fp) < fp)
            {
                break;
            }
            /// 无用指针判断
            if (!(fp + 4) || !(uint64_t *)fp)
            {
                break;
            }

            std::stringstream sstemp;
            /// 获取程序计数指针
            sstemp << "#" << backline << ", fp address: " << (uint64_t *)fp << ", lr:"
                   << (uint64_t *)lr
                   << std::endl;

            Logger::logInfo(TRACKER_TAG, sstemp.str().c_str());

            ss << transformFormat(backline, lr, baseIsolateInstructions)
               << std::endl;

            /// 更新指针, 理论上是 +4
            lr = *((uint64_t *)(fp + 4));
            fp = *((uint64_t *)fp);
            backline++;
        }

        FileSaveUtil::saveStrFile(staceSavePath, ss.str());

        /// get ss stack...
        Logger::logInfo(TRACKER_TAG, ss.str().c_str());
        ss.clear();
    }
}

void Tracker::registerSignalListener()
{
    printCurrentThreadInfo(TRACKER_TAG);
    /// 获取主线程对象
    mainThread = pthread_self();
    actionNew.sa_sigaction = trackerActionWithSignum;
    sigemptyset(&actionNew.sa_mask);
    actionNew.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    if (sigaction(SIGUSR1, &actionNew, nullptr) == 0)
    {
        isRegister = 1;
    }
    else
    {
        isRegister = 0;
    }
}

void Tracker::unregisterSignalListener()
{
    if (isRegister)
    {
        sigaction(SIGUSR1, nullptr, &actionNew);
    }
    isRegister = 0;
    mainThread = 0;
}

void Tracker::track()
{
    printCurrentThreadInfo(TRACKER_TAG);
    if (mainThread > 0)
    {
        /// this will crash??
        /// if main thread is out pointer....
        pthread_kill(mainThread, RAISE_SIGN);
    }
}

void Tracker::setBaseIsolateInstructions(uint64_t isolateInstructions, uint64_t vmInstructions)
{
    baseIsolateInstructions = isolateInstructions;
    baseVmInstructions = vmInstructions;
}

Tracker::~Tracker()
{
    mainThread = 0;
};
